<template>
    <div class="property">
        <div class="item_name" :title="`${property.name}(${property.description})`">{{ property.name }}</div>
        <div class="readonly_flag">
            <span @click.stop="openPop" title="设置属性值" style="cursor: pointer;color: rgba(230, 230, 230, 1);">⚙</span>
        </div>
        <div v-if="!readonly && defaultValue !== undefined && !(JSON.stringify(stringRef)===JSON.stringify(defaultValue))" class="checkbox"
            @click.stop.prevent="resetDefult" @mouseover="mouseFlag = true" @mouseout="mouseFlag = false">
            <es-icon :name="'huaban'" :color="mouseFlag ? 'rgba(230, 230, 230, 1)' : 'rgba(230, 230, 230, 0.4)'"
                :size="14" />
        </div>

    </div>
    <Window :title="'函数编辑器'" :show="collectionShow" @cancel="collectionShow = false" @ok="changeOk" :width="800"
        :height="500">
        <div style="margin-left:10px">
            <button @click="copyJs">复制</button>
            <button @click="importJsFile">导入</button>
            <button @click="saveJsFile">导出</button>
            <button @click="sampleShow = true">示例文档</button>
        </div>
        <iframe ref="mainIframe" :src="iframeSrc" @load="loadIframe" frameborder="0"
            style="width:100% ; height:calc(100% - 50px);"></iframe>
    </Window>
    <SamplePanel :jsonStr="sampleValue ?? '<center>暂无数据</center>'" :isShow="sampleShow" @changeShow="changeSampleShow">
    </SamplePanel>
</template>

<script setup lang="ts">
import { onBeforeUnmount, ref } from "vue";
import { createVueDisposer, getAssetsDir, toReadonlyVueRef, toVR } from 'vue-xe2-plugin/dist-node/components/xe2/tools';
import { getOpenFileHandle, getSaveFileHandle, getTextFromFile, saveFile } from "xbsj-xe2/dist-node/xe2-base-objects";
import { copyClipboard } from "../commons/base/copyClipboard";
import { getUuid } from "../commons/base/getUuid";

import SamplePanel from '../commons/base/SamplePanel.vue';
// import Window from "../../WindowPop.vue";
import { Message } from "earthsdk-ui";
import Window from "../../../commom/Window.vue";
import { PropertyCompCallbackFuncParamsType } from "./base";

const props = withDefaults(defineProps<{
    property: any
    type: string
}>(), {
});
const emits = defineEmits<{
    (e: 'callback', params: PropertyCompCallbackFuncParamsType): void;
}>();
const mouseFlag = ref(false)

const iframeSrc = getAssetsDir() + '/monaco-editor/js-editor.html';

const collectionShow = ref(false)
const sampleShow = ref(false)
const mainIframe = ref<HTMLIFrameElement>();
const { property } = props
const readonly = property.readonly
const disposer = createVueDisposer(onBeforeUnmount)
const stringRef = readonly ? toReadonlyVueRef<string | undefined>(disposer, property.reactVar, s => s && s as string) : toVR<string | undefined>(disposer, property.reactVar, s => s && s as string)
const defaultValue = property.defaultValue ?? '';
const sampleValue: string | undefined = property.sampleValue
const stringComRef = ref('')
const changeSampleShow = (flag: boolean) => {
    sampleShow.value = flag
}
const resetDefult = () => {
    stringRef.value = defaultValue
}
const copyJs = async () => {
    const str = await getJs()
    copyClipboard(str)//复制
}
const importSetJs = async (str: string) => {
    await setJs(str)
}
const importJsFile = async () => { //导入文件
    try {
        Message.warning('正在打开..')
        const handle = await getOpenFileHandle('js');
        if (!handle) return;
        const str = await getTextFromFile(handle);
        if (!str) return;
        importSetJs(str)
        Message.success('导入成功！')
    } catch (error) {
        Message.error(`打开失败！ error: ${error}`);
    }
}
const saveJsFile = async () => {
    const str = await getJs()
    saveAs(str)
}
const saveAs = async (evalStr: string) => {//导出下载
    try {
        Message.warning('正在另存为..');
        const handle = await getSaveFileHandle('js');
        if (!handle) return;
        await saveFile(handle, evalStr);
        Message.success('另存成功!');
    } catch (error) {
        Message.error(`另存失败! error: ${error}`);
    }
}
const openPop = () => {
    mouseFlag.value=false
    if (stringRef.value === undefined) {
        stringComRef.value = defaultValue
    } else {
        stringComRef.value = JSON.parse(JSON.stringify(stringRef.value))
    }
    collectionShow.value = true
}
const loadIframe = async () => {
    if (!stringComRef.value) {
        return;
    }
    await setJs(stringComRef.value)
}
const changeOk = async () => {
    const str = await getJs()
    stringRef.value = str
    collectionShow.value = false
}
function setJs(value: string) {
    return new Promise<void>((resolve, reject) => {
        if (!mainIframe.value || !mainIframe.value.contentWindow) {
            return;
        }
        const setKey = getUuid()
        mainIframe.value.contentWindow.postMessage({ type: 'setJs', id: setKey, value })
        const time = setTimeout(() => {
            removeEventListener('message', messageSetEventWatch, false);
            reject();
        }, 10000);
        const messageSetEventWatch = (messageEvent: MessageEvent<{ type: string, id: string, status: string } | undefined>) => {
            var data = messageEvent.data;
            if (!data || (data.type && data.type !== 'setJsReturn') || (data.id && data.id !== setKey)) {
                return;
            }
            removeEventListener('message', messageSetEventWatch, false);
            clearTimeout(time)
            if (data.status === 'ok') {
                resolve();
            } else {
                reject();
            }
        }
        addEventListener('message', messageSetEventWatch, false);
    })

}
function getJs() {
    return new Promise<string>((resolve, reject) => {
        if (!mainIframe.value || !mainIframe.value.contentWindow) {
            return;
        }
        const getKey = getUuid()
        mainIframe.value.contentWindow.postMessage({ type: 'getJs', id: getKey })
        const time = setTimeout(() => {
            removeEventListener('message', messageGetEventWatch, false);
            reject();
        }, 10000);
        const messageGetEventWatch = (messageEvent: MessageEvent<{ type: string, id: string, status: string, value: string | undefined } | undefined>) => {
            var data = messageEvent.data;
            if (!data || (data.type && data.type !== 'getJsReturn') || (data.id && data.id !== getKey)) {
                return;
            }
            removeEventListener('message', messageGetEventWatch, false);
            clearTimeout(time)
            if (data.status === 'ok' && data.value) {
                resolve(data.value);
            } else {
                reject();
            }
        }
        addEventListener('message', messageGetEventWatch, false);
    })
}
</script>
<style scoped>
.property {
    width: 100%;
    display: flex;
    align-items: center;
}

.item_name {
    width: 70px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
    color: rgba(230, 230, 230, 1);
}

.readonly_flag {
    flex: 1;

}

.readonly_true {
    cursor: not-allowed;
    cursor: no-drop;
}

button {
    width: 80px;
    height: 32px;
    background: rgba(28, 28, 29, 0.60);
    border-radius: 4px;
    border: 1px solid rgba(28, 28, 29, 0.60);
    cursor: pointer;
    color: rgba(230, 230, 230, 1);
    margin-left: 20px;
    margin-top: 10px;
}

button:hover {
    border: 1px solid #2c68f7;
}

.readonly_flag {
    width: 100%;
    height: 100%;
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: center;
}
.checkbox {
    width: 20px;
    height: 20px;
    cursor: pointer;
    border: 1px solid rgba(230, 230, 230, 0.4);
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 4px;
    margin-left: 10px;
}
</style>